package com.dd.shop4j.common.helper;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

import com.dd.shop4j.common.helper.Table.Column;

abstract class AbstractSQLHepler {

	List<Table> tables = new ArrayList<Table>();
	static final String database = "shop4j";
	//admin,goods,member,order,sys
	static final String fix = "member";
	static final String packageName = "com.dd.shop4j." + fix;
	static final String table_fix = fix + "_log";
	static final String bak_dir = "D:/java/code_bak/" + fix + System.currentTimeMillis();
	
	public void createModel() {
		for (Table table : tables) {
			String content = getModelContent(table, packageName);
			String filePath = "src/main/java/" + packageName.replace(".", "/") + "/model/" + firstUpper(getJavaName(table.getName())) + ".java";
			writetoFile(filePath, content);
		}
	}

	public void createMapper() {
		for (Table table : tables) {
			String content = getMapperContent(table, packageName);
			String filePath = "src/main/java/" + packageName.replace(".", "/") + "/mapper/" + firstUpper(getJavaName(table.getName())) + "Mapper.java";
			writetoFile(filePath, content);
		}
	}

	public void createMapperXML() {
		for (Table table : tables) {
			String content = getMapperXMLContent(table, packageName);
			String filePath = "src/main/java/" + packageName.replace(".", "/") + "/mapper/" + firstUpper(getJavaName(table.getName())) + "Mapper.xml";
			writetoFile(filePath, content);
		}
	}

	public void createService() {
		for (Table table : tables) {
			System.out.println(table.getName());
		}
	}

	public void createController() {
		for (Table table : tables) {
			System.out.println(table.getName());
		}
	}
	
	
	//////////////////////////////////////////////////////////////////////////
	
	protected String firstUpper(String name) {
		return name.substring(0, 1).toUpperCase() + name.substring(1);
	}
	
	protected String firstLower(String name) {
		return name.substring(0, 1).toLowerCase() + name.substring(1);
	}
	
	protected String getClassName(String tableName) {
		return firstUpper(getJavaName(tableName));
	}
	
	protected String getJavaName(String name) {
		name = name.toLowerCase();
		String[] cs = name.split("_");
		String jname = "";
		for (String c : cs) {
			jname += firstUpper(c);
		}
		return firstLower(jname);
	}
	
	protected void writetoFile(String filePath, String content) {
		FileWriter writer = null;
		try {
			File file = new File(filePath);
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			} else {
				//备份一下原文件
				if (file.exists() && file.isFile()) {
					File bakDir = new File(bak_dir);
					bakDir.mkdirs();
					FileUtils.copyFileToDirectory(file, bakDir);
				}
			}
			writer = new FileWriter(file);
			writer.write(content);
			System.out.println("文件生成：" + filePath);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (writer != null) writer.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	protected String getModelContent(Table table, String packageName) {
		List<Column> columns = table.getColumns();
		StringBuffer context = new StringBuffer();
		context.append("package ").append(packageName).append(".model;\n\n");
		context.append(table.getImports()).append("\n\n");
		context.append("/**\n");
		context.append(" * ").append(table.getName()).append(" - ").append(StringUtils.isEmpty(table.getComment()) ? "<空>" : table.getComment()).append("\n");
		context.append(" * \n");
		context.append(" * @author 唐小恕 ").append(new SimpleDateFormat("yyyy-MM-dd").format(new Date())).append("\n");
		context.append(" * @version 1.0 \n");
		context.append(" */\n");
		context.append("public class ").append(getClassName(table.getName())).append(" {\n");
		for (Column c : columns) {
			context.append("\t/**\n");
			context.append("\t * ").append(c.getType()).append("(").append(c.getLength()).append(")\n");
			context.append("\t * ").append(StringUtils.isEmpty(c.getCommect()) ? "<空>" : c.getCommect()).append("\n");
			if (StringUtils.isNotEmpty(c.getDefaultValue())) {
				context.append("\t * 默认值:").append(c.getDefaultValue()).append("\n");
			}
			if (c.isPk()) {
				context.append("\t * 主键字段").append("\n");
			}
			if (!c.isNullable()) {
				context.append("\t * 字段不允许为空").append("\n");
			}
			context.append("\t */\n");
			context.append("\tprivate ");
			context.append(c.getJAVAType()).append(" ");
			context.append(getJavaName(c.getName())).append(";\n");
		}
		context.append("\n");
		for (Column c : columns) {
			context.append("\tpublic ");
			String type = c.getJAVAType() + " ";
			context.append(type);
			context.append("get").append(firstUpper(getJavaName(c.getName()))).append("() {\n");
			context.append("\t\treturn ").append(getJavaName(c.getName())).append(";");
			context.append("\n\t}\n\n");
			
			context.append("\tpublic void set").append(firstUpper(getJavaName(c.getName()))).append("(").append(type).append(getJavaName(c.getName())).append(") {\n");
			context.append("\t\tthis.").append(getJavaName(c.getName())).append(" = ").append(getJavaName(c.getName())).append(";");
			context.append("\n\t}\n\n");
		}
		context.append("}");
		return context.toString();
	}

	protected String getMapperXMLContent(Table table, String packageName) {
		StringBuffer context = new StringBuffer();
		List<Column> columns = table.getColumns();
		String tableName = table.getName();
		String mapperPackge = packageName + ".mapper";
		context.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
		context.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n");
		context.append("<mapper namespace=\"").append(mapperPackge).append(".").append(getClassName(tableName)).append("Mapper\">\n");
		context.append("  <!-- ").append(table.getComment()).append("ResultMap -->\n");
		context.append("  <resultMap id=\"BaseResultMap\" type=\"").append(packageName).append(".model.").append(getClassName(tableName)).append("\">\n");
		for (Column c : columns) {
			context.append("    <").append(c.isPk() ? "id" : "result").append(" column=\"").append(c.getName()).append("\" jdbcType=\"").append(c.getSQLType()).append("\" property=\"").append(getJavaName(c.getName())).append("\" />\n");
		}
		context.append("  </resultMap>\n\n");
		
		context.append("  <!--  字段列表   -->\n");
		context.append("  <sql id=\"columnList\">\n    ");
		for (int i = 0; i < columns.size(); i++) {
			context.append(columns.get(i).getName());
			if (i < columns.size() - 1) {
				context.append(", ");
			}
		}
		context.append("\n  </sql>\n\n");
		
		context.append("  <!--  添加数据   -->\n");
		context.append("  <insert id=\"insertSelective\" parameterType=\"").append(packageName).append(".model.").append(getClassName(tableName)).append("\"");
		for (Column c : columns) {
			if (c.isPk() && c.isAuto()) {
				context.append(" useGeneratedKeys=\"true\" keyProperty=\""+getJavaName(c.getName())+"\"");
				break;
			}
		}
		context.append(">\n");
		context.append("     insert into ").append(tableName).append("\n");
		context.append("     <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
		for (Column c : columns) {
			context.append("       <if test=\"").append(getJavaName(c.getName())).append(" != null\">\n");
			context.append("         ").append(c.getName()).append(",\n");
			context.append("       </if>\n");
		}
		context.append("     </trim>\n");
		context.append("     values \n");
		context.append("     <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
		for (Column c : columns) {
			context.append("       <if test=\"").append(getJavaName(c.getName())).append(" != null\">\n");
			context.append("         #{").append(getJavaName(c.getName())).append(",jdbcType=").append(c.getSQLType()).append("},\n");
			context.append("       </if>\n");
		}
		context.append("     </trim>\n");
		context.append("  </insert>\n\n");
		
		context.append("  <!--  根据主键修改选择数据   -->\n");
		context.append("  <update id=\"updateSelectiveByPrimaryKey\" parameterType=\"").append(packageName).append(".model.").append(getClassName(tableName)).append("\">\n");
		context.append("     update ").append(tableName).append("\n");
		context.append("     <set>\n");
		for (Column c : columns) {
			if (c.isPk())
				continue;
			context.append("       <if test=\"").append(getJavaName(c.getName())).append(" != null\">\n");
			context.append("         ").append(c.getName()).append(" = #{").append(getJavaName(c.getName())).append(",jdbcType=").append(c.getSQLType()).append("},\n");
			context.append("       </if>\n");
		}
		context.append("     </set>\n");
		for (Column c : columns) {
			if (c.isPk()) {
				context.append("     where ").append(c.getName()).append(" = #{").append(getJavaName(c.getName())).append(",jdbcType=").append(c.getSQLType()).append("}\n");
				break;
			}
		}
		context.append("  </update>\n\n");
		
		context.append("  <!--  根据主键修改数据   -->\n");
		context.append("  <update id=\"updateByPrimaryKey\" parameterType=\"").append(packageName).append(".model.").append(getClassName(tableName)).append("\">\n");
		context.append("     update ").append(tableName).append("\n");
		context.append("     <set>\n");
		for (Column c : columns) {
			if (c.isPk())
				continue;
			context.append("       ").append(c.getName()).append(" = #{").append(getJavaName(c.getName())).append(",jdbcType=").append(c.getSQLType()).append("},\n");
		}
		context.append("     </set>\n");
		for (Column c : columns) {
			if (c.isPk()) {
				context.append("     where ").append(c.getName()).append(" = #{").append(getJavaName(c.getName())).append(",jdbcType=").append(c.getSQLType()).append("}\n");
				break;
			}
		}
		context.append("  </update>\n\n");
		
		context.append("  <!--  根据主键删除数据   -->\n");
		context.append("  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.");
		for (Column c : columns) {
			if (c.isPk()) {
				context.append(c.getJAVAType());
				break;
			}
		}
		context.append("\">\n");
		context.append("    delete from ").append(tableName).append("\n");
		for (Column c : columns) {
			if (c.isPk()) {
				context.append("    where ").append(c.getName()).append(" = #{").append(getJavaName(c.getName())).append(",jdbcType=").append(c.getSQLType()).append("}\n");
				break;
			}
		}
		context.append("  </delete>\n\n");
		
		context.append("  <!--  根据主键批量删除数据   -->\n");
		context.append("  <delete id=\"deleteByPrimaryKeys\" parameterType=\"java.lang.");
		for (Column c : columns) {
			if (c.isPk()) {
				context.append(c.getJAVAType());
				break;
			}
		}
		context.append("\">\n");
		context.append("    delete from ").append(tableName).append("\n");
		for (Column c : columns) {
			if (c.isPk()) {
				context.append("    where ").append(c.getName()).append(" in \n");
				context.append("        <foreach item=\"idItem\" collection=\"array\" open=\"(\" separator=\",\" close=\")\">\n");
				context.append("			#{idItem}\n");
				context.append("        </foreach>\n");
				break;
			}
		}
		context.append("  </delete>\n\n");
		
		context.append("  <!--  根据主键查询数据   -->\n");
		context.append("  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n");
		context.append("    select \n");
		context.append("      <include refid=\"columnList\" />\n");
		context.append("    from ").append(tableName).append("\n");
		for (Column c : columns) {
			if (c.isPk()) {
				context.append("    where ").append(c.getName()).append(" = #{").append(getJavaName(c.getName())).append(",jdbcType=").append(c.getSQLType()).append("}\n");
				break;
			}
		}
		context.append("  </select>\n\n");
		
		context.append("  <!--  分页查询条件   -->\n");
		context.append("  <sql id=\"queryPageCond\">\n");
		context.append("    <where>\n");
		context.append("      1 = 1\n");
		context.append("      <if test=\"entity != null\">\n");
		for (Column c : columns) {
			context.append("        <if test=\"entity.").append(getJavaName(c.getName())).append(" != null\">\n");
			context.append("          and ").append(c.getName()).append(" = #{entity.").append(getJavaName(c.getName())).append("}\n");
			context.append("        </if>\n");
		}
		context.append("      </if>\n");
		context.append("    </where>\n");
		context.append("  </sql>\n\n");
		
		context.append("  <!--  分页条件查询   -->\n");
		context.append("  <select id=\"queryPageBySelective\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n");
		context.append("    select\n");
		context.append("      <include refid=\"columnList\"/>\n");
		context.append("    from ").append(tableName).append("\n");
		context.append("	<if test=\"entity != null\">\n");
		context.append("		<include refid=\"queryPageCond\"/>\n");
		context.append("	</if>\n");
		context.append("	<if test=\"orderby != null\">\n");
		context.append("		order by #{orderby} #{orderType}\n");
		context.append("	</if>\n");
		context.append("	limit #{start},#{limit}\n");
		context.append("  </select>\n\n");
		
		context.append("  <!--  条件查询记录行数   -->\n");
		context.append("  <select id=\"getCountBySelective\" parameterType=\"map\" resultType=\"java.lang.Integer\">\n");
		context.append("    select \n");
		context.append("      count(1)\n");
		context.append("    from ").append(tableName).append("\n");
		context.append("	  <if test=\"entity != null\">\n");
		context.append("		<include refid=\"queryPageCond\"/>\n");
		context.append("	  </if>\n");
		context.append("  </select>\n\n");
		
		context.append("  <!--  默认查询条件   -->\n");
		context.append("  <sql id=\"queryCond\">\n");
		context.append("    <where>\n");
		context.append("    1 = 1\n");
		for (Column c : columns) {
			context.append("    <if test=\"").append(getJavaName(c.getName())).append(" != null\">\n");
			context.append("      and ").append(c.getName()).append(" = #{").append(getJavaName(c.getName())).append("}\n");
			context.append("    </if>\n");
		}
		context.append("    </where>\n");
		context.append("  </sql>\n\n");
		
		context.append("  <!--  条件查询   -->\n");
		context.append("  <select id=\"queryBySelective\" parameterType=\"").append(packageName).append(".model.").append(getClassName(tableName)).append("\" resultMap=\"BaseResultMap\">\n");
		context.append("    select \n");
		context.append("      <include refid=\"columnList\"/>\n");
		context.append("    from ").append(tableName).append("\n");
		context.append("      <include refid=\"queryCond\" />\n");
		context.append("  </select>\n\n");
		
		context.append("</mapper>");
		
		return context.toString();
	}

	protected String getMapperContent(Table table, String packageName) {
		try {
			StringBuffer context = new StringBuffer();
			BufferedReader reader = new BufferedReader(new FileReader(new File("src/main/java/com/dd/shop4j/common/helper/mapper_template.txt")));
			String line = null;
			while ((line = reader.readLine()) != null) {
				context.append(line).append("\n");
			}
			String result = context.toString()
				.replace("{packageName}", packageName)
				.replace("{className}", getClassName(table.getName()))
				.replace("{comment}", table.getComment())
				.replace("{tableName}", table.getName())
				.replace("{date}", new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
				.replace("{version}", "1.0")
				;
			for (Column c : table.getColumns()) {
				if (c.isPk()) {
					result = result.replace("{pkType}", c.getJAVAType());
					break;
				}
			}
			reader.close();
			return result;
		}catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
}
